package com.opages.netty.demo.lesson.dark_horse1;

import com.opages.netty.demo.lesson.ByteBufferUtil;
import io.netty.util.CharsetUtil;
import org.junit.Test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channel;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * @author daizhong.liu
 * @create 2021-12-28 10:55
 **/
public class TestByteBuffer {
    @Test
    public void testByteBuffer() {
        ByteBuffer buffer = ByteBuffer.allocate(10);
        buffer.put((byte)97);
        ByteBufferUtil.debugAll(buffer);

        // 向buffer中写入4个字节的数据
        buffer.put(new byte[]{98, 99, 100, 101});
        ByteBufferUtil.debugAll(buffer);

        // 获取数据(切换为读模式)
        // 调用flip切换模式，此时position为0，表示从第0个数据开始读取
        System.err.println("切换flip");
        buffer.flip();
        ByteBufferUtil.debugAll(buffer);
        System.out.println(buffer.get());
        System.out.println(buffer.get());
        ByteBufferUtil.debugAll(buffer);

        // 使用compact切换模式
        // 调用compact切换模式，此时position及其后面的数据被压缩到ByteBuffer前面去了
        // 此时position为3，会覆盖之前的数据
        System.err.println("切换compact");
        buffer.compact();
        ByteBufferUtil.debugAll(buffer);

        // 再次写入
        System.err.println("再次写入");
        buffer.put((byte)102);
        buffer.put((byte)103);
        ByteBufferUtil.debugAll(buffer);
    }

    @Test
    public void translate() {
        String hello = "hello";
        ByteBuffer encode = StandardCharsets.UTF_8.encode(hello);
        ByteBufferUtil.debugAll(encode);

        ByteBuffer buffer = ByteBuffer.wrap(hello.getBytes(CharsetUtil.UTF_8));
        ByteBufferUtil.debugAll(buffer);
    }
    @Test
    public void testStickyBag() {
        ByteBuffer buffer = ByteBuffer.allocate(32);
        //模拟粘包
        buffer.put("hello world\nnetty is ok!\n stic".getBytes(CharsetUtil.UTF_8));
        stickyHandler(buffer);
        //模拟拆包
        buffer.put("ky bag to handler \n".getBytes(CharsetUtil.UTF_8));
        stickyHandler(buffer);
    }

    public void stickyHandler(ByteBuffer buffer) {
        //切换为读模式
        buffer.flip();
        for (int i = 0; i < buffer.limit(); i++) {
            //以\n为拆包的分割符，buffer.get(index)不会变换position的位置
            if (buffer.get(i)=='\n') {
                int splitLen = i + 1 - buffer.position();
                ByteBuffer curByteBuffer = ByteBuffer.allocate(splitLen);
                for (int j = 0; j < splitLen; j++) {
                    //buffer.get()会变换position的位置
                    curByteBuffer.put(buffer.get());
                }
                ByteBufferUtil.debugAll(curByteBuffer);
            }
        }
        //会将变换position的位置前移至0，且未读的数据往前复制
        buffer.compact();
    }
    @Test
    public void testTransferTo() {
        transferTo("D:\\nginx-1.15.11.zip","D:\\target_nginx.zip");
    }

    public void transferTo(String srcPath,String targetPath) {
        try (
                FileInputStream fis = new FileInputStream(srcPath);
                FileOutputStream fos = new FileOutputStream(targetPath);
                FileChannel fisChannel = fis.getChannel();
                FileChannel fosChannel = fos.getChannel();
        ){
            long capacity  = fisChannel.size();
            long fisSize = fisChannel.size();
            while(capacity  > 0) {
                //返回传输字节数,使用transferTo实现零拷贝
                capacity  -= fisChannel.transferTo(fisSize - capacity, capacity, fosChannel);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
}
